package com.fadadianqi.mall.product;

import com.fadadianqi.goods.model.Brand;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.mall.product.model.ItemSPU;
import com.fadadianqi.mall.product.service.ItemSPUService;
import com.fadadianqi.search.AbstractIndexService;
import com.fadadianqi.search.IndexPathHelper;
import com.yeqiangwei.commons.util.Pagination;
import com.yeqiangwei.commons.util.StringHelper;
import com.yeqiangwei.commons.util.ValidatorHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.fadadianqi.search.IndexPathHelper.IndexEnum.SPU;

/**
 * Created by aroot on 2/27/14.
 */
@Service
public class SpuIndexService extends AbstractIndexService {

    private static final Log log = LogFactory.getLog(SpuIndexService.class);

    public static final String FIELD_ID = "id";
    public static final String FIELD_NAME = "name";
    public static final String FIELD_DISPLAY_NAME = "displayName";
    public static final String FIELD_DETAILS = "details";
    public static final String FIELD_BRAND_NAME = "brandName";
    public static final String FIELD_PINYIN = "pinyin";
    private static Boolean IS_RUNNING = Boolean.FALSE;
    private IndexPathHelper indexPathHelper = new IndexPathHelper(SPU);
    private String newPath;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ItemSPUService itemSPUService;

    @Override
    public String getCurrentIndexPath() {
        return indexPathHelper.getIndexPath();
    }

    @Override
    protected String getNewIndexPath() {
        newPath = indexPathHelper.createNewPath();
        log.debug("#getNewIndexPath#..., newPath: " + newPath);
        return newPath;
    }

    @Override
    protected void build(IndexWriter writer, boolean rebuild) throws Exception {
        log.debug("#building..., rebuild: " + rebuild);
        synchronized (writer) {
            // 写操作保持同步
            int total = 0;
            if (rebuild) {
                total = itemSPUService.countAll();
            } else {
                total = itemSPUService.countAllNotIndexed();
            }
            int limit = 1000;
            int pages = total / limit;
            if (total % limit != 0) {
                pages++;
            }
            for (int page = 1; page <= pages; page++) {
                Pagination pagination = null;
                List<ItemSPU> list = null;
                if (rebuild) {
                    pagination = new Pagination(page, limit);
                    list = itemSPUService.findAll(pagination);
                } else {
                    pagination = new Pagination(1, limit);
                    list = itemSPUService.findAllNotIndexed(pagination);

                }
                if (ValidatorHelper.isEmpty(list)) {
                    continue;
                }
                for (ItemSPU spu : list) {
                    try {
                        writer.addDocument(documentBuilder(spu));
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error(e.toString());
                    }
                    spu.setIsIndexed(Boolean.TRUE);
                    itemSPUService.updateIsIndexed(spu);
                }
            }
            writer.optimize();
            writer.close(true);
        }
        log.debug("#built success!, rebuild: " + rebuild);
    }

    @Override
    protected void changeIndexPath() {
        indexPathHelper.savePath(newPath);
    }

    @Override
    protected Document documentBuilder(Object object) throws Exception {

        ItemSPU spu = (ItemSPU) object;
        Brand brand = goodsService.getBrandById(spu.getBrandId());

        Document doc = new Document();

        Field id = new Field(FIELD_ID, spu.getId(), Field.Store.YES, Field.Index.NOT_ANALYZED);
        doc.add(id);

        Field name = new Field(FIELD_NAME, spu.getName(), Field.Store.YES, Field.Index.ANALYZED);
        doc.add(name);

        Field displayName = new Field(FIELD_DISPLAY_NAME, spu.getDisplayName(), Field.Store.YES, Field.Index.ANALYZED);
        doc.add(displayName);

        if(spu.getDetails() != null) {
            Field details = new Field(FIELD_DETAILS, spu.getDetails(), Field.Store.YES, Field.Index.ANALYZED);
            doc.add(details);
        }

        StringBuilder pinyin = new StringBuilder();
        pinyin.append(StringHelper.toPinyin(spu.getName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(spu.getName()));
        pinyin.append(" ");
        pinyin.append(StringHelper.toPinyin(spu.getDisplayName()));
        pinyin.append(" ");
        pinyin.append(super.toPinyinIndexContent(spu.getDisplayName()));
        pinyin.append(" ");

        if(brand != null) {
            Field brandName = new Field(FIELD_BRAND_NAME, brand.getName(), Field.Store.YES, Field.Index.ANALYZED);
            doc.add(brandName);
            //
            pinyin.append(StringHelper.toPinyin(brand.getName()));
            pinyin.append(" ");
            pinyin.append(super.toPinyinIndexContent(brand.getName()));
            pinyin.append(" ");
        }

        Field pinyinField = new Field(FIELD_PINYIN, pinyin.toString(), Field.Store.YES, Field.Index.ANALYZED);
        doc.add(pinyinField);
        if (log.isDebugEnabled()) {
            log.debug("#documentBuilder# " + doc.toString());
        }
        return doc;
    }


    public synchronized boolean isRunning() {
        return IS_RUNNING;
    }

    protected synchronized void lock() {
        IS_RUNNING = true;
    }

    protected synchronized void unlock() {
        IS_RUNNING = false;
    }
}
